import math
import os
from scipy import optimize
from Measure.distance.getD import getD
from Utilities.AutoGetOperator.selectionMethod.selectPackage import get_func
from ScoreFunction.getS import getS

import numpy as np
root_path = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))  # 项目的根目录
project_path = os.path.join(root_path, r'Operators')  # 项目所在目录
file_a_path = os.path.join(project_path, 'OperatorIVQROF.py')  # 目标文件目录
Operator_IVQ_ROFS=get_func(file_a_path,'Operator_IVQ_ROFS')

class SEAC:
    def __init__(self,matrix,beta,q):
        self.matrix = matrix
        self.beta = beta
        self.q = q

    def add(self, a1, a2, q=0, *waste1, **waste2):
        """
            funciton    : 区间值广义正交模糊集的 和 运算
            a1          : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2          : 一个模糊集, 形式:（[x,y]，[x,y]）
            return      : 加法结果, 形式:（[x,y]，[x,y]）
        """
        u_1_f, u_1_r, v_1_f, v_1_r = *a1[0], *a1[1]
        u_2_f, u_2_r, v_2_f, v_2_r = *a2[0], *a2[1]
        if q <= 0:
            q = self.q
        u_f = (u_1_f ** q + u_2_f ** q - (u_1_f ** q) * (u_2_f ** q)) ** (1 / q)
        u_r = (u_1_r ** q + u_2_r ** q - (u_1_r ** q) * (u_2_r ** q)) ** (1 / q)
        v_f = (v_1_f) * (v_2_f)
        v_r = (v_1_r) * (v_2_r)
        return ([u_f, u_r], [v_f, v_r])

    def multi(self, a1, a2, q=0, *waste1, **waste2):
        """
            funciton    : 区间值广义正交模糊集的 积 运算
            a1          : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2          : 一个模糊集, 形式:（[x,y]，[x,y]）
            return      : 乘法结果, 形式:（[x,y]，[x,y]）
        """
        u_1_f, u_1_r, v_1_f, v_1_r = *a1[0], *a1[1]
        u_2_f, u_2_r, v_2_f, v_2_r = *a2[0], *a2[1]
        if q <= 0:
            q = self.q
        u_f = (u_1_f) * (u_2_f)
        u_r = (u_1_r) * (u_2_r)
        v_f = (v_1_f ** q + v_2_f ** q - (v_1_f ** q) * (v_2_f ** q)) ** (1 / q)
        v_r = (v_1_r ** q + v_2_r ** q - (v_1_r ** q) * (v_2_r ** q)) ** (1 / q)
        return ([u_f, u_r], [v_f, v_r])

    def kmulti(self, a, k, q=0, *waste1, **waste2):
        """
            function : 区间值广义正交模糊集的 数乘 运算
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            k        : ka 的常数 k
            return   : 数乘 运算法则 的值，形式：（[x,y]，[x,y]）
        """
        u_a_f, u_a_r, v_a_f, v_a_r = *a[0], *a[1]
        if q <= 0:
            q = self.q
        u_f = (1 - (1 - (u_a_f) ** q) ** k) ** (1 / q)
        u_r = (1 - (1 - (u_a_r) ** q) ** k) ** (1 / q)
        v_f = (v_a_f) ** k
        v_r = (v_a_r) ** k
        return ([u_f, u_r], [v_f, v_r])

    def pow(self, a, k, q=0, *waste1, **waste2):
        """
            function : 区间值广义正交模糊集的 乘方 运算
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            k        : ka 的常数 k
            return   : 乘方 运算法则 的值，形式：（[x,y]，[x,y]）
        """
        u_a_f, u_a_r, v_a_f, v_a_r = *a[0], *a[1]
        if q <= 0:
            q = self.q
        v_f = (1 - (1 - (v_a_f) ** q) ** k) ** (1 / q)
        v_r = (1 - (1 - (v_a_r) ** q) ** k) ** (1 / q)
        u_f = (u_a_f) ** k
        u_r = (u_a_r) ** k
        return ([u_f, u_r], [v_f, v_r])
    def derta_N(self):
        row=len(self.matrix)
        column = len(self.matrix[0])
        derta_temp =[]
        for j in range(column):
            # 求每列的平均值
            x_sum = self.matrix[0][0]
            for i in range(row):
                x_sum =self.add(x_sum,self.matrix[i][j])
            x_ave = self.kmulti(x_sum,1/row)

            total = 0
            for i in range(row):
                total +=pow(getD(self.matrix[i][j],x_ave,2).getDistance(),2)
            derta_temp.append(pow((total/row),1/2))

        derta=[round(i / sum(derta_temp), 4) for i in derta_temp]
        return derta

    def pi_N(self):
        row=len(self.matrix)
        column = len(self.matrix[0])
        r = []
        for j in range (column):
            r_temp=[]
            for l in range(column):
                # 求l列的平均值
                x_sum_l = self.matrix[0][0]
                for i in range(row):
                    x_sum_l = self.add(x_sum_l,self.matrix[i][l])
                x_ave_l = self.kmulti(x_sum_l , 1/row)

                # 求每j列的平均值
                x_sum_j = self.matrix[0][0]
                for i in range(row):
                    x_sum_j = self.add(x_sum_j,self.matrix[i][j])
                x_ave_j = self.kmulti(x_sum_j, 1 / row)

                total_1 = 0
                total_2 = 0
                total_3 = 0
                for i in range(row):
                    total_1  += (getD(self.matrix[i][j],x_ave_j,2).getDistance())*(getD(self.matrix[i][l],x_ave_l,2).getDistance())
                    total_2  += pow(getD(self.matrix[i][j],x_ave_j,2).getDistance(),2)
                    total_3  += pow(getD(self.matrix[i][l],x_ave_l,2).getDistance(),2)
                r_temp.append(total_1/pow((total_2*total_3),1/2))
            r.append(r_temp)

        pi_j =[]
        for j in range(len(r)):
            sum_r_jl = 0
            for l in range(len(r[0])):
                sum_r_jl+=(1-r[j][l])
            pi_j.append(sum_r_jl)

        pi = [round(i / sum(pi_j), 4) for i in pi_j]
        return pi
    def getResult(self):
        derta = self.derta_N()
        pi = self.pi_N()
    # 定义所求函数(平方)
        def f1(W):
            L = 0
            # L3 = self.kmulti(self.matrix[0][0], W[0])
            L3 = [[0,0],[0,0]]
            for i in range(len(self.matrix)):
                for j in range(len(self.matrix[0])):
                    if i == 0 and j == 0:
                        continue
                    L +=pow(W[j]-derta[j],2)
                    L +=pow(W[j]-pi[j],2)
                    L1 = self.kmulti(self.matrix[i][j],W[j])
                    L3 = self.add(L3,L1)
            L4 = getS(L3,3).getScore()
            L2=self.beta*L -L4
            return L2
        # 定义约束函数
        def g(W):
            sum = 0
            for i in range(len(self.matrix[0])):
                sum += W[i]
            return sum - 1

        # 定义约束
        constraints = [dict(type='eq', fun=g)]
        # 定义变量边界
        weightBounds = ([0,1],[0,1],[0,1],[0,1],[0,1])

        # 优化
        res = optimize.minimize(f1, (0.5,0.5,0.5,0.5,0.5), method='SLSQP', constraints=constraints,
                                bounds=weightBounds)
        # res = optimize.minimize(f1, (0, 0, 0, 0, 0, 0), method='SLSQP', constraints=constraints,
        #                         bounds=weightBounds)
        return res.x

# def getS(matrix,W):
#     sum =0
#     for i in range(len(matrix)):
#         for j in range(len(matrix[0])):
#             sum+=W[j]*matrix[i][j]
#     return sum
if __name__ == '__main__':
    # matrix = [
    #    [([0.81539, 0.91785], [0.17128, 0.28772]), ([0.12374, 0.22949], [0.55729, 0.67911]), ([0.84635, 0.95753], [0.10662, 0.21768]), ([0.73433, 0.90407], [0.20174, 0.23691]),],
    #    [([0.79202, 0.84776], [0.10917, 0.11366]), ([0.29818, 0.3131], [0.47785, 0.64139]), ([0.14316, 0.29861], [0.78271, 0.8032]), ([0.01997, 0.33824], [0.71369, 0.85874]),  ],
    #    [([0.89511, 0.90987], [0.1782, 0.21547]), ([0.19584, 0.25518], [0.4043, 0.51519]), ([0.24707, 0.43495], [0.71766, 0.74854]), ([0.08338, 0.28006], [0.1259, 0.34247]),   ],
    #    [([0.09222, 0.1264], [0.78533, 0.81673]), ([0.24999, 0.31601], [0.63687, 0.7492]), ([0.13707, 0.23335], [0.75133, 0.88383]), ([0.70681, 0.77778], [0.00605, 0.18418]),  ],
    #    [([0.1876, 0.28807], [0.42117, 0.57172]), ([0.1311, 0.19959], [0.7644, 0.81178]), ([0.06145, 0.20426], [0.86783, 0.89045]), ([0.74275, 0.86356], [0.14231, 0.25652])  ]
    #   ]
    matrix =[([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
    ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]),([0.95, 0.06], [0.19, 0.1])]

    d = SEAC(matrix,4,3).getResult()
    print(d)
    # for i in range(len(matrix)):
    #     print(d.getRes(i),getS(matrix,i,d.getRes(i)))
    # t = []
    # for i in range(len(matrix)):
    #     s = getS(matrix,i,d.getRes(i))
    #     t.append(s)
    # t.sort()
    # print(t)
    # p = [0.21510051,0.20924173 ,0.13085575 ,0.2024061  ,0.13426422 ,0.10813168]
    # for i in range(len(matrix)):
    #     print(getS(matrix,i,0.13085575))


#[0.21510051 0.20924173 0.13085575 0.2024061  0.13426422 0.10813168] 0.43111707050120696
# 0.10813168,39,[0.4444, 0.2857, 0.8974, 0.6667, 0.8631, 0.9707]